const axios = require('axios');
const path = require('path');
const DataStore = require('../utils/dataStore');
const logger = require('../utils/logger');
const config = require('../config');

/**
 * 天气服务
 * 获取和处理天气信息
 */
class WeatherService {
  constructor() {
    // 初始化数据存储
    this.dataStore = new DataStore(path.join(__dirname, '../../', config.dataFiles.weather));
    this.initialized = false;
    this.weatherCache = new Map();
    this.cacheTTL = 30 * 60 * 1000; // 30分钟缓存
  }

  /**
   * 初始化天气服务
   */
  async init() {
    try {
      await this.dataStore.init();
      this.initialized = true;
      logger.info('天气服务初始化成功');
    } catch (error) {
      logger.error(`天气服务初始化失败: ${error.message}`);
      throw error;
    }
  }

  /**
   * 确保服务已初始化
   */
  async ensureInitialized() {
    if (!this.initialized) {
      await this.init();
    }
  }

  /**
   * 获取当前天气
   * @param {string} city - 城市名称
   * @param {Object} options - 请求选项
   * @returns {Promise<Object>} 天气数据
   */
  async getCurrentWeather(city, options = {}) {
    await this.ensureInitialized();

    try {
      // 检查API密钥
      if (!config.weather.apiKey) {
        throw new Error('天气API密钥未配置');
      }

      // 检查缓存
      const cacheKey = `current:${city}`;
      const cachedData = this.weatherCache.get(cacheKey);
      if (cachedData && Date.now() - cachedData.timestamp < this.cacheTTL) {
        logger.debug(`使用缓存的天气数据: ${city}`);
        return cachedData.data;
      }

      // 准备请求参数
      const params = {
        q: city,
        appid: config.weather.apiKey,
        units: options.units || config.weather.units,
        lang: options.lang || config.weather.lang
      };

      // 发送API请求
      logger.debug(`请求当前天气数据: ${city}`);
      const response = await axios.get(`${config.weather.apiUrl}/weather`, { params });

      // 处理响应
      if (response.data) {
        // 格式化天气数据
        const weatherData = this.formatWeatherData(response.data);
        
        // 保存到缓存
        this.weatherCache.set(cacheKey, {
          data: weatherData,
          timestamp: Date.now()
        });
        
        // 保存到数据存储
        await this.saveWeatherRecord(city, weatherData);
        
        return weatherData;
      } else {
        throw new Error('天气API返回空数据');
      }
    } catch (error) {
      logger.error(`获取当前天气失败: ${error.message}`);
      
      // 尝试从历史记录中获取最新数据
      const latestRecord = await this.getLatestWeatherRecord(city);
      if (latestRecord) {
        logger.info(`使用历史天气数据: ${city}`);
        return latestRecord;
      }
      
      throw error;
    }
  }

  /**
   * 获取天气预报
   * @param {string} city - 城市名称
   * @param {number} days - 预报天数（1-5）
   * @param {Object} options - 请求选项
   * @returns {Promise<Object>} 天气预报数据
   */
  async getWeatherForecast(city, days = 5, options = {}) {
    await this.ensureInitialized();

    try {
      // 检查API密钥
      if (!config.weather.apiKey) {
        throw new Error('天气API密钥未配置');
      }

      // 限制天数范围
      days = Math.min(Math.max(1, days), 5);

      // 检查缓存
      const cacheKey = `forecast:${city}:${days}`;
      const cachedData = this.weatherCache.get(cacheKey);
      if (cachedData && Date.now() - cachedData.timestamp < this.cacheTTL) {
        logger.debug(`使用缓存的天气预报数据: ${city}, ${days}天`);
        return cachedData.data;
      }

      // 准备请求参数
      const params = {
        q: city,
        appid: config.weather.apiKey,
        units: options.units || config.weather.units,
        lang: options.lang || config.weather.lang,
        cnt: days
      };

      // 发送API请求
      logger.debug(`请求天气预报数据: ${city}, ${days}天`);
      const response = await axios.get(`${config.weather.apiUrl}/forecast/daily`, { params });

      // 处理响应
      if (response.data && response.data.list) {
        // 格式化天气预报数据
        const forecastData = {
          city: response.data.city.name,
          country: response.data.city.country,
          forecast: response.data.list.map(day => this.formatForecastData(day)),
          timestamp: new Date().toISOString()
        };
        
        // 保存到缓存
        this.weatherCache.set(cacheKey, {
          data: forecastData,
          timestamp: Date.now()
        });
        
        return forecastData;
      } else {
        throw new Error('天气预报API返回空数据');
      }
    } catch (error) {
      logger.error(`获取天气预报失败: ${error.message}`);
      throw error;
    }
  }

  /**
   * 格式化天气数据
   * @param {Object} data - 原始天气数据
   * @returns {Object} 格式化后的天气数据
   */
  formatWeatherData(data) {
    return {
      city: data.name,
      country: data.sys.country,
      temperature: {
        current: Math.round(data.main.temp),
        feelsLike: Math.round(data.main.feels_like),
        min: Math.round(data.main.temp_min),
        max: Math.round(data.main.temp_max)
      },
      weather: {
        main: data.weather[0].main,
        description: data.weather[0].description,
        icon: data.weather[0].icon
      },
      wind: {
        speed: data.wind.speed,
        deg: data.wind.deg
      },
      humidity: data.main.humidity,
      pressure: data.main.pressure,
      visibility: data.visibility,
      sunrise: new Date(data.sys.sunrise * 1000).toISOString(),
      sunset: new Date(data.sys.sunset * 1000).toISOString(),
      timestamp: new Date().toISOString()
    };
  }

  /**
   * 格式化天气预报数据
   * @param {Object} data - 原始预报数据
   * @returns {Object} 格式化后的预报数据
   */
  formatForecastData(data) {
    return {
      date: new Date(data.dt * 1000).toISOString(),
      temperature: {
        day: Math.round(data.temp.day),
        min: Math.round(data.temp.min),
        max: Math.round(data.temp.max),
        night: Math.round(data.temp.night),
        evening: Math.round(data.temp.eve),
        morning: Math.round(data.temp.morn)
      },
      weather: {
        main: data.weather[0].main,
        description: data.weather[0].description,
        icon: data.weather[0].icon
      },
      humidity: data.humidity,
      pressure: data.pressure,
      wind: {
        speed: data.speed,
        deg: data.deg
      },
      clouds: data.clouds,
      precipitation: data.pop
    };
  }

  /**
   * 保存天气记录
   * @param {string} city - 城市名称
   * @param {Object} weatherData - 天气数据
   */
  async saveWeatherRecord(city, weatherData) {
    try {
      // 创建记录对象
      const record = {
        id: this.dataStore.generateId(),
        city: city.toLowerCase(),
        data: weatherData,
        createdAt: new Date().toISOString()
      };

      // 保存到数据存储
      await this.dataStore.add(record);
      logger.debug(`已保存天气记录: ${city}`);
    } catch (error) {
      logger.error(`保存天气记录失败: ${error.message}`);
    }
  }

  /**
   * 获取最新的天气记录
   * @param {string} city - 城市名称
   * @returns {Promise<Object|null>} 天气数据或null
   */
  async getLatestWeatherRecord(city) {
    try {
      // 查询指定城市的记录
      const records = await this.dataStore.query(item => 
        item.city && item.city.toLowerCase() === city.toLowerCase()
      );

      // 按时间排序并返回最新记录
      if (records.length > 0) {
        records.sort((a, b) => 
          new Date(b.createdAt) - new Date(a.createdAt)
        );
        return records[0].data;
      }
      
      return null;
    } catch (error) {
      logger.error(`获取天气历史记录失败: ${error.message}`);
      return null;
    }
  }

  /**
   * 获取城市的天气历史记录
   * @param {string} city - 城市名称
   * @param {number} limit - 最大记录数
   * @returns {Promise<Array>} 天气记录数组
   */
  async getWeatherHistory(city, limit = 10) {
    await this.ensureInitialized();

    try {
      // 查询指定城市的记录
      const records = await this.dataStore.query(item => 
        item.city && item.city.toLowerCase() === city.toLowerCase()
      );

      // 按时间排序并限制数量
      records.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt));
      return records.slice(0, limit);
    } catch (error) {
      logger.error(`获取天气历史记录失败: ${error.message}`);
      throw error;
    }
  }

  /**
   * 清除天气缓存
   * @param {string} city - 城市名称（可选，不提供则清除所有缓存）
   */
  clearCache(city) {
    if (city) {
      // 清除指定城市的缓存
      const currentKey = `current:${city}`;
      const forecastKey = `forecast:${city}:5`;
      this.weatherCache.delete(currentKey);
      this.weatherCache.delete(forecastKey);
      logger.debug(`已清除城市天气缓存: ${city}`);
    } else {
      // 清除所有缓存
      this.weatherCache.clear();
      logger.debug('已清除所有天气缓存');
    }
  }
}

// 导出单例
module.exports = new WeatherService();